package com.pig4cloud.pigx.common.customize.mongo.utils;

import com.mongodb.lang.Nullable;
import com.pig4cloud.pigx.common.customize.utils.ReflectUtil;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * MongoDB工具类
 *
 * @date 2022/8/12 17:16
 */
@Component
public class MongoUtils {

	/**
	 * 固定排除字段
	 */
	public static final List<String> FIXED_EXCLUDE_FIELDS = Arrays.asList("id",
			"createBy",
			"createTime",
			"updateBy",
			"updateTime",
			"isDeleted");

	public static final String COMMON_ERROR_MSG = "数据异常，无法生成update对象";


	/**
	 * 组装MongoDB Update 参数
	 *
	 * @param entity 实体类
	 * @return {@link Update}
	 * @date 2022/8/12 17:48
	 */
	public static Update getUpdate(@NotNull(message = COMMON_ERROR_MSG) Object entity) {
		return getUpdate(entity, null);
	}

	/**
	 * 组装MongoDB Update 参数
	 *
	 * @param entity       实体类
	 * @param excludeFiled 排除的属性
	 * @return {@link Update}
	 * @date 2022/8/12 18:00
	 */
	public static Update getUpdate(@NotNull(message = COMMON_ERROR_MSG) Object entity,
								   @Nullable List<String> excludeFiled) {

		List<Field> filedList = ReflectUtil.getFiledAsList(entity.getClass());

		// 添加固定排除字段
		if (CollectionUtils.isEmpty(excludeFiled)) {
			excludeFiled = FIXED_EXCLUDE_FIELDS;
		} else {
			excludeFiled.addAll(FIXED_EXCLUDE_FIELDS);
		}

		Update update = new Update();
		for (Field i : filedList) {
			// 检验是否是排除的字段，id、isDeleted固定排除排除固定字段
			if (excludeFiled.contains(i.getName())) {
				continue;
			}

			Method getter = ReflectUtil.getGetter(entity, i.getName());

			// getter不为空
			if (Objects.isNull(getter)) {
				continue;
			}

			try {
				Object value = getter.invoke(entity);

				// 值为空
				if (Objects.isNull(value)) {
					continue;
				}

				update.set(i.getName(), value);

			} catch (IllegalAccessException | InvocationTargetException e) {
				throw new RuntimeException(e);
			}
		}

		return update;
	}
}
